import {
  config,
  envKey,
  regionAreaList,
  timeout
} from "../config.js";
import {
  Toast,
  popup,
  fitterItem,
  useNetWork,
  whetherLogin,
  isLoading,
  getRequestBaseUrl,
  getRegionKey,
  errorToast
} from "./util.js";



let isRefreshing = false; // 是否正在刷新的标记
let requests = []; //重试队列，每一项将是一个待执行的函数形式

let anewParams = {
  url: "/sys/operate/refresh_token",
  method: "POST",
  data: {},
};

const whiteListUrl = [
  // 我的房屋模块
  "/indeed/house/houseList",
  "/indeed/house/unitsDetailsInfo",
  "/indeed/population/addPersonInfo",
  "/indeed/population/getIdPersonInfo",
  "/indeed/house/selectPoliceHouseMain",
  "/indeed/house/setisMainId",
  "/indeed/house/deletePoliceHouseMain",
  "/indeed/population/updatePersonInfo",
  "/indeed/population/deletePersonInfo",
  // 单位场所
  "/company/message/page",
  "/company/message/detail",
  "/company/message/save",
  "/company/message/legal_authenticate",
  "/company/message/update_company",
  "/company/message/delete",
  "/company/message/get_qr_code",
  "/company/message/send_sms",
  "/company/message/company_change_detail",
  "/company/message/check_legal_info",
  "/company/certificate/save",
  "/company/certificate/detail",
  "/company/user/page",
  "/company/user/insert",
  "/company/user/set_up",
  "/company/user/find_responsible",
  "/company/message/business_detail",
  "/company/message/save_business",
  "/company/user/find_company_info",
  "/company/message/duty_authenticate",
  "/company/message/check_duty_info",
  "/company/info_detail/find_company",
  "/company/info_detail/save",
  "/company/duty_person/detail",
  "/company/message/mapPoints",
  "/company/FireDrill/page",
  "/company/FireDrill/save",
  "/company/fireTraining/page",
  "/machine/maintenanceProntList",
  "/company/fireTraining/save",
  "/company/FireDrill/detail",
  "/company/fireTraining/detail",
  "/industry/information/tree",
  "/police/user/find_police_agency_list",
  "/sys/document_company/sign_page",
  "/sys/document_company/sign",
  // 印刷业和机修页
  "/machine/maintenanceRecordsList",
  "/machine/maintenanceRecordsAdd",
  "/machine/maintenanceRecordsUpdate",
  "/machine/getCarNumberList",
  "/machine/maintenanceProntList",
  "/machine/maintenanceProntAdd",

  // 特色功能
  '/industry/pawnRecordList',
  '/industry/addPawnRecordDetails',
  '/industry/addWasteRecyclingRecordDetails',

  '/industry/addWasteRecyclingRecordDetails',
  '/industry/wasteRecyclingRecordList',

  '/industry/addPhoneRecyclingRecord',
  '/industry/addunlockRecord',
  '/industry/phoneRecyclingRecordList',
  '/industry/getPawnRecordDetails',
  '/industry/getWasteRecyclingRecordDetails',
  '/industry/getIdPhoneRecyclingRecord',
  '/industry/unlockRecordList',
  '/industry/getUnlockRecordById',
  '/industry/oil_sale/add',
  '/industry/oil_sale/oilSaleRecordDetails',
  '/industry/oil_sale/page',
  '/indeed/house/selectHeadBybm',

  "/sys/document_company/find_wait_sign_count",
  // "/common/activity_declaration/page",

  // * 实有房屋
  "/indeed/house/houseList", // 查询房屋列表
  "/indeed/house/unitsRoomList", // 查询标准地址下的房屋采集信息
  "/indeed/house/unitsDetailsInfo", // 查询房屋信息详情
  "/indeed/house/addUnits", // 新增房屋
  "/indeed/house/addUnits", // 编辑房屋信息
  "/indeed/house/addPoliceHouseMain", // 新增房屋负责人
  "/indeed/house/selectPoliceHouseMain", // 房屋负责人列表查询
  "/indeed/house/setisMainId", // 根据id设置主要负责人
  "/indeed/house/deletePoliceHouseMain", // 删除主要负责人
  '/indeed/house/upzdstSyfwnfo',
  '/indeed/house/upzdszJsonssInfo',

  // * 实有人口
  "/indeed/population/populationList", // 查询实有人口信息
  "/indeed/population/getIdPersonInfo", // 查询实有人口详情
  "/indeed/population/addPersonInfo", // 新增实有人口信息
  "/indeed/population/updatePersonInfo", // 修改实有人口信息
  "/indeed/population/deletePersonInfo", // 删除实有人口

  // * 出租屋
  "/rentinghouse/houseList", // 查询出租屋列表
  "/rentinghouse/rentingHouseInfo", // 查询出租屋详情
  "/rentinghouse/historicalContracts", // 查询历史合同
  "/rentinghouse/tenantList", // 查询租客列表
  "/rentinghouse/lessorList", // 查询房屋负责人信息
  "/rentinghouse/addRentContract", // 新增租房合同
  "/rentinghouse/contractDetails", // 查询合同详情
  "/rentinghouse/updateRentContract", // 修改租房合同 & 续租合同
  "/rentinghouse/contractTermination", // 退租合同 & 中止合同
  "/rentinghouse/updateRentContract",

  // * 实有单位
  "/company/message/enterpriseList", // 获取辅警网格员实有单位详情
  "/common/area/likeUnitsRoomList", // 模糊查询房屋地址

  // 待办事项
  "/police/check_unqualified/find_agency_count",
  "/police/check_task/find_task_page",
  "/sys/document_company/wait_sign_page",
  // 刷新 token
  "/sys/operate/refresh_token",

  // 首页
  "/common/risk_reporting/page",
  "/common/clue_reporting/page",
  "/industry/public_security/detail",
  "/police/check_task/find_task_page",
  "/common/disputes_reporting/page",
  "/common/complaint_message/page",
  '/common/clue_reporting/save',
  '/common/risk_reporting/save',
  '/common/complaint_message/save',
  '/common/advise_message/save',
  '/industry/public_security/save',
  '/common/disputes_reporting/save',
  // 投诉建议
  "/common/advise_message/page",
  '/indeed/house/houseTypeList',
  '/common/area/unreadSum',
  '/featured/employees/operation',
  '/feedback/add',
  '/feedback/list',
  '/feedback/detail',
  '/missingAddressReporting/jurisdictionList',
  '/missingAddressReporting/list',
  '/missingAddressReporting/add',
  '/missingAddressReporting/detail',

  '/dsSyAerocraft/aerocraftList',
  '/dsSyAerocraft/aerocraftAdd',
  '/dsSyAerocraft/getAerocraftIdInfo',
  '/dsSyCar/dsSyCarList',
  '/dsSyCar/getdsSyCarIdInfo',
  '/dsSyCar/dsSyCarAdd',
  '/dsSyDog/dogAdd',
  '/dsSyDog/dogList',
  '/dsSyDog/getDogIdInfo',
  '/dsSyCow/dsSyCowAdd',
  '/dsSyCow/dsSyCowList',
  '/dsSyCow/getdsSyCowIdInfo',
  '/dsSyGastank/dsSyGastankAdd',
  '/dsSyGastank/dsSyGastankList',
  '/dsSyGastank/getdsSyGastankIdInfo',
  '/dsSyNjj/dsSyNjjAdd',
  '/dsSyNjj/dsSyNjjList',
  '/dsSyNjj/getdsSyNjjIdInfo',
  '/dsSyQtwp/toolAdd',
  '/dsSyQtwp/toolList',
  '/dsSyQtwp/getToolId',
  '/dsSySlingshot/dsSySlingshotAdd',
  '/dsSySlingshot/dsSySlingshotList',
  '/dsSySlingshot/getdsSySlingshotIdInfo'
];

function pathRewrite(url) {
  if (whiteListUrl.includes(url)) {
    return `/${config.role}${url}`;
  } else {
    return url;
  }
}

function fun(url, method, data, loading = true, headers) {
  url = pathRewrite(url);
  if (uni.getStorageSync("refreshToken")) {
    anewParams.data = {
      refreshToken: uni.getStorageSync("refreshToken"),
    };
  }
  const role = config.role;
  const requestTokenName = config.roleConfig[role].requestTokenName;
  let token = uni.getStorageSync("X-MINI-TOKEN");
  let promise = new Promise((resolve, reject) => {
    let header = {
      "content-type": "application/json", // 默认值
    };

    if (token) {
      header[requestTokenName] = token;
    }
    if (loading) {
      uni.showLoading({
        title: "加载中...",
        mask: true,
      });
    }

    useNetWork(); // 判断是否有网络
    uni.request({
      url: getRequestBaseUrl() + url,
      method,
      timeout: timeout,
      data,
      dataType: "json",
      header: headers || header,
      success(res) {
        if (loading) {
          uni.hideLoading();
        }
        let statusCode = res.statusCode;
        switch (statusCode) {
          case 200:
            let code = res.data.code;
            switch (code) {
              case 314:
                errorToast(res.data.message);
                uni.clearStorageSync();
                setTimeout(() => {
                  uni.reLaunch({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                }, 1000);
                break;
              case 320:
                errorToast(res.data.message);
                uni.clearStorageSync();
                setTimeout(() => {
                  uni.reLaunch({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                }, 1000);
                break;
              case 500:
                if (url != "/sys/logout") {
                  errorToast(res.data.message);
                }
                reject(res.data);
                break;
              case 1000:
                errorToast(res.data.message);
                reject(res.data);
                break;
              case 200:
                isRefreshing = false;
                resolve(res.data);
                break;
                // 400 是真的失败了
              case 400:
                errorToast(res.data.message);
                reject(res.data);
                break;
              case 1001:
                errorToast(
                  res.data.message + "，请检查房屋是否正确或重新选择与户主关系"
                );
                reject(res.data);
                break;
              default:
                resolve(res.data);
                break;
            }
            break;
          case 400:
            reject(res.data);
            break;
          case 404:
            reject(res.data);
            errorToast("请联系服务人员，错误代码：404,资源无法找到");
            break;
          case 500:
            if (res.data.message.indexOf("重新登录") != -1) {
              if (token) {
                errorToast("登录状态失效，请重新登录");
                uni.clearStorageSync();
                setTimeout(() => {
                  uni.reLaunch({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                }, 1500);
                reject(res);
              }
            } else {
              errorToast("服务器内部错误，错误代码：500");
            }
            break;
          case 502:
            reject(res.data);
            errorToast("请联系服务人员，错误代码：502");
            break;
          case 401:
            //这里是重点：让这个Promise一直处于Pending状态（即不调用resolve）
            new Promise((resolve) => {
              requests.push((token) => {
                if (!data) {
                  data = {};
                }
                token = `${token}`;
                // 用函数形式将 resolve 存入，等待刷新后再执行
                resolve(fun(url, method, data));
              });
            });

            if (!isRefreshing) {
              console.log("access token过期");
              isRefreshing = true; //第一个请求后，后面请求都不进入执行请求
              //调用刷新token的接口
              return (
                fun(anewParams.url, anewParams.method, anewParams.data)
                .then((data) => {
                  if (data.code == 200) {
                    uni.setStorageSync("X-MINI-TOKEN", data.result.token);
                    uni.setStorageSync("refreshToken", data.result.refreshToken); //刷新token 参数值
                    // token 刷新后将数组的方法重新执行
                    // requests.forEach((cb) => cb(data.result.token));
                    // 重新调用档期啊页面的生命周期函数
                    const pages = getCurrentPages()
                    const curPage = pages[pages.length - 1]
                    curPage.onLoad(curPage.options)
                    curPage.onShow()
                    curPage.onReady()
                    requests = []; // 重新请求完清空
                    return;
                  }
                })
                // 除了 http code === 200 和 后台返回 code 都不是 200 的时候都走 catch 里面
                .catch((err) => {
                  if (
                    (err.code === 400 && err.message === "登录已过期") ||
                    (err.code === 400 && err.message === "未获取刷新token") ||
                    (err.code === 400 && err.message === "用户名或密码错误")
                  ) {
                    errorToast(err.message + "0000");
                    setTimeout(() => {
                      uni.removeStorageSync("X-MINI-TOKEN");
                      uni.reLaunch({
                        url: "/pages/beforeLogin/beforeLogin",
                      });
                    }, 500);
                  }
                  //获取token失败，删除旧token，跳到登录页
                  //   try {
                  //     wx.removeStorageSync('X-MINI-TOKEN');
                  //   } catch (error) {}
                  //   uni.redirectTo({
                  //     url: "/pages/beforeLogin/beforeLogin",
                  //   });
                  //   return Promise.reject(err);
                })
              );
            }
            break;
          default:
            break;
        }
      },
      fail(res) {
        console.log(res)
        reject(res);
        errorToast("调用接口失败！");
        if (loading) {
          uni.hideLoading();
        }
      },
    });
  });
  return promise;
}

// export let getAction = (url, data, header) =>
//   fun(url, "GET", fitterItem(data), true, header);


export let getAction = (url, data, header) => {
  return uni.$u.http.get(url, {
    params: data
  })
}

// export let postAction = (url, data, header) =>
//   fun(url, "POST", data, true, header);

export let postAction = (url, data, header) => {
  return uni.$u.http.post(url, data, {
    header
  })
}


// export let putAction = (url, data, header) =>
//   fun(url, "PUT", data, true, header);


export let putAction = (url, data, header) => {
  const region = getRegionKey()
  if (regionAreaList.includes(region)) {
    return uni.$u.http.post(url, data, {
      header: {
        ...header,
        'X-HTTP-Method-Override': 'PUT'
      }
    })
  } else {
    return uni.$u.http.put(url, data, {
      header: {
        ...header,
      }
    })
  }
}

// export let deleteAction = (url, data, header) =>
//   fun(url, "DELETE", data, true, header);


export let deleteAction = (url, data, header) => {
  // 获取当前 地域 
  const region = getRegionKey()
  if (regionAreaList.includes(region)) {
    return uni.$u.http.post(url, data, {
      header: {
        ...header,
        'X-HTTP-Method-Override': 'DELETE'
      }
    })
  } else {
    return uni.$u.http.delete(url, data, {
      header: {
        ...header,
      }
    })
  }
}

export function setHttpConfig() {
  uni.$u.http.setConfig((config) => {
    /* config 为默认全局配置*/
    config.baseURL = getRequestBaseUrl(); /* 根域名 */
    config.timeout = timeout
    return config
  })
}

export function initHttp() {

  setHttpConfig()

  // 请求拦截器
  uni.$u.http.interceptors.request.use((httpConfig) => { // 可使用async await 做异步操作
    useNetWork()

    httpConfig.header['content-type'] = "application/json"
    const role = config.role;
    const requestTokenName = config.roleConfig[role].requestTokenName;
    let token = uni.getStorageSync("X-MINI-TOKEN");

    if (token) {
      httpConfig.header[requestTokenName] = token;
    }

    // 重写请求路径
    httpConfig.url = pathRewrite(httpConfig.url)
    return httpConfig
  }, httpConfig => { // 可使用async await 做异步操作
    return Promise.reject(httpConfig)
  })

  // 响应拦截器

  // 刷新token标识
  let isRefreshingAccessToken = false;
  // token队列
  let requestList = [];

  uni.$u.http.interceptors.response.use(
    async (response) => {
      isLoading(false)
      /* 对响应成功做点什么 可使用async await 做异步操作*/
      // http code == 200
      // 判断 服务端返回的 code 
      let code = response.data.code
      switch (code) {
        // 真正的响应成功
        case 200:
          return Promise.resolve(response.data)
          break;
          // 后台返回的错误
        case 400:
          errorToast(response.data.message)
          return Promise.reject(response.data)
          break
          // 默认 promise 返回成功
        default:
          return Promise.resolve(response.data)
          break
      }
      // return Promise.resolve(response.data)
    }, async (error) => {
      isLoading(false)
      console.log('resError', error)
      /*  对响应错误做点什么 （statusCode !== 200）*/
      const {
        config
      } = error
      // 如果返回的是 401 
      switch (error.statusCode) {
        case 401: {
          // 判断 有 refreshToken 的时候再去刷新
          const refreshToken = uni.getStorageSync("refreshToken")
          console.log('isRefreshingAccessToken', isRefreshingAccessToken, refreshToken)
          if (refreshToken) {
            if (isRefreshingAccessToken) {
              // 失败的时候，将 promise 挂起 到队列中
              return new Promise((resolve) => {
                requestList.push({
                  resolve,
                  config
                })
              })
            }
            if (!config.url.includes('/sys/operate/refresh_token')) {
              try {
                // 开启正在刷新 token 的请求
                isRefreshingAccessToken = true
                console.log('刷新 token')
                const resRefresh = await uni.$u.http.request({
                  url: "/sys/operate/refresh_token",
                  method: "POST",
                  data: {
                    refreshToken
                  },
                })
                console.log(resRefresh)
                if (resRefresh.code == 200) {
                  uni.setStorageSync("X-MINI-TOKEN", resRefresh.result.token);
                  uni.setStorageSync("refreshToken", resRefresh.result.refreshToken); //刷新token 参数值

                  //执行请求列表
                  requestList.forEach(({
                    config,
                    resolve
                  }) => {
                    resolve(uni.$u.http.request(config))
                  });
                  // 重试完了清空这个队列
                  requestList = [];
                  //还原标识
                  //重新执行本次请求
                  return uni.$u.http.request(config);
                } else if (resRefresh.code == 320) {
                  errorToast(resRefresh.message);
                  setTimeout(() => {
                    uni.removeStorageSync("X-MINI-TOKEN");
                    uni.reLaunch({
                      url: "/pages/beforeLogin/beforeLogin",
                    });
                  }, 500);
                }
              } catch (err) {
                if (
                  // 判断 token 真的失效了
                  (err.code === 400 && err.message === "登录已过期") ||
                  (err.code === 400 && err.message === "未获取刷新token") ||
                  (err.code === 400 && err.message === "用户名或密码错误")
                ) {
                  errorToast(err.message + "0000");
                  setTimeout(() => {
                    uni.removeStorageSync("X-MINI-TOKEN");
                    uni.reLaunch({
                      url: "/pages/beforeLogin/beforeLogin",
                    });
                  }, 500);
                }
              } finally {
                // 不管刷新成功还是失败，都要吧正在刷新重置为 false
                isRefreshingAccessToken = false;
              }
            }
          }
          break
        }
        case 502: {
          errorToast("请联系服务人员，错误代码：502");
          return Promise.reject(error)
          break;
        }
      }
      // 截取出来 错误的 message 信息
      const errorMessage = error.errMsg
      let processedMessage = errorMessage.replace(/\s/g, '').toLowerCase()
      if (error.errno === 5 || ~processedMessage.indexOf('timeout')) {
        // 对请求超时的判断
        Toast('请求超时，请稍后再试！')
        // 关闭 loading 
      }
      return Promise.reject(error)
    })
}